﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions ;
using System.Threading.Tasks;
using System.Web;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using BoYuan.Framework.Uitility.Extensions;

namespace BoYuan.Framework.Uitility
{
    /// <summary>
    /// http相关工具类
    /// </summary>
    public class HttpHelper
    {
        /// <summary>
        /// get请求方法
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        public static string HttpGet(string url)
        {
            HttpWebRequest request = null;
            HttpWebResponse response = null;
            try
            {
                request = System.Net.WebRequest.Create(url) as HttpWebRequest;
                request.Method = "GET";
                response = request.GetResponse() as HttpWebResponse;
            }
            catch (WebException exception)
            {
                if (exception.Status == WebExceptionStatus.ProtocolError)
                {
                    response = (HttpWebResponse)exception.Response;
                }
                if (exception.Status == WebExceptionStatus.ConnectFailure)
                {
                    return exception.Message;
                }
            }
            catch (Exception)
            {
                if (response != null)
                {
                    response.Close();
                }
                return string.Empty;
            }

            if (response != null)
            {
                Encoding enc = string.IsNullOrEmpty(response.CharacterSet) ? Encoding.UTF8 : Encoding.GetEncoding(response.CharacterSet);
                using (StreamReader sr = new StreamReader(response.GetResponseStream(), enc))
                {
                    string tempStr = sr.ReadToEnd();
                    response.Close();
                    return tempStr;
                }
            }
            return string.Empty;
        }

        /// <summary>
        /// post提交,获取返回参数
        /// </summary>
        /// <param name="url">url</param>
        /// <param name="value">参数(username=a&pwd=b)</param>
        /// <returns></returns>
        public static string HttpPost(string url, string value)
        {
            HttpWebResponse response = null;
            HttpWebRequest request = null;
            try
            {
                request = (HttpWebRequest)System.Net.WebRequest.Create(url);
                request.Method = "POST";
                request.ContentType = HttpContentType.WWW_FORM_URLENCODED;// "application/x-www-form-urlencoded";
                byte[] bytes = Encoding.UTF8.GetBytes(value);
                request.ContentLength = bytes.Length;
                Stream requestStream = request.GetRequestStream();
                requestStream.Write(bytes, 0, bytes.Length);
                requestStream.Close();
                response = (HttpWebResponse)request.GetResponse();
            }
            catch (WebException exception)
            {
                if (exception.Status == WebExceptionStatus.ProtocolError)
                {
                    response = (HttpWebResponse)exception.Response;
                }
                if (exception.Status == WebExceptionStatus.ConnectFailure)
                {
                    return exception.Message;
                }
            }
            catch (Exception)
            {
                if (response != null)
                {
                    response.Close();
                }
                return string.Empty;
            }

            if (response != null)
            {
                Encoding enc = string.IsNullOrEmpty(response.CharacterSet)?Encoding.UTF8 : Encoding.GetEncoding(response.CharacterSet);
                using (StreamReader sr = new StreamReader(response.GetResponseStream(), enc))
                {
                    string tempStr = sr.ReadToEnd();
                    response.Close();
                    return tempStr;
                }
            }
            return string.Empty;
        }

        /// <summary>
        /// HTTP 内容类型(Content-Type)
        /// </summary>
        public class HttpContentType
        {
            /// <summary>
            /// 资源类型：普通文本
            /// </summary>
            public const string TEXT_PLAIN = "text/plain";

            /// <summary>
            /// 资源类型：JSON字符串
            /// </summary>
            public const string APPLICATION_JSON = "application/json";

            /// <summary>
            /// 资源类型：未知类型(数据流)
            /// </summary>
            public const string APPLICATION_OCTET_STREAM = "application/octet-stream";

            /// <summary>
            /// 资源类型：表单数据(键值对)
            /// </summary>
            public const string WWW_FORM_URLENCODED = "application/x-www-form-urlencoded";

            /// <summary>
            /// 资源类型：表单数据(键值对)。编码方式为 gb2312
            /// </summary>
            public const string WWW_FORM_URLENCODED_GB2312 = "application/x-www-form-urlencoded;charset=gb2312";

            /// <summary>
            /// 资源类型：表单数据(键值对)。编码方式为 utf-8
            /// </summary>
            public const string WWW_FORM_URLENCODED_UTF8 = "application/x-www-form-urlencoded;charset=utf-8";

            /// <summary>
            /// 资源类型：多分部数据
            /// </summary>
            public const string MULTIPART_FORM_DATA = "multipart/form-data";
        }


        /// <summary>
        /// 以 multipart/form-data 形式post请求
        /// </summary>
        /// <param name="strUrl">url</param>
        /// <param name="postParaList">参数集合</param>
        /// <returns></returns>
        public static string HttpPost_FormData(string strUrl, List<PostDateClass> postParaList)
        {
            //https://www.cnblogs.com/zuferj115/p/7382797.html
            try
            {
                string responseContent = "";
                var memStream = new MemoryStream();
                var webRequest = (HttpWebRequest)WebRequest.Create(strUrl);
                // 边界符
                var boundary = "---------------" + DateTime.Now.Ticks.ToString("x");
                // 边界符
                var beginBoundary = Encoding.ASCII.GetBytes("--" + boundary + "\r\n");
                // 最后的结束符
                var endBoundary = Encoding.ASCII.GetBytes("--" + boundary + "--\r\n");
                memStream.Write(beginBoundary, 0, beginBoundary.Length);
                // 设置属性
                webRequest.Method = "POST";
                webRequest.Timeout = 10000;
                webRequest.ContentType = "multipart/form-data; boundary=" + boundary;
                for (int i = 0; i < postParaList.Count; i++)
                {
                    PostDateClass temp = postParaList[i];
                    if (temp.PostDataType == PostDateClass.DateType.FileType)
                    {
                        var fileStream = new FileStream(temp.Value, FileMode.Open, FileAccess.Read);
                        // 写入文件
                        const string filePartHeader =
                            "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\n" +
                            "Content-Type: application/octet-stream\r\n\r\n";
                        var header = string.Format(filePartHeader, temp.Key, temp.Value);
                        var headerbytes = Encoding.UTF8.GetBytes(header);
                        memStream.Write(headerbytes, 0, headerbytes.Length);
                        var buffer = new byte[1024];
                        int bytesRead; // =0
                        while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
                        {
                            memStream.Write(buffer, 0, bytesRead);
                        }
                        string end = "\r\n";
                        headerbytes = Encoding.UTF8.GetBytes(end);
                        memStream.Write(headerbytes, 0, headerbytes.Length);
                        fileStream.Close();
                    }
                    else //if (temp.PostDataType == PostDateClass.DateType.StringType)
                    {
                        // 写入字符串的Key
                        var stringKeyHeader = "Content-Disposition: form-data; name=\"{0}\"" +
                                       "\r\n\r\n{1}\r\n";
                        var header = string.Format(stringKeyHeader, temp.Key, temp.Value);
                        var headerbytes = Encoding.UTF8.GetBytes(header);
                        memStream.Write(headerbytes, 0, headerbytes.Length);
                    }

                    if (i != postParaList.Count - 1)
                        memStream.Write(beginBoundary, 0, beginBoundary.Length);
                    else
                        // 写入最后的结束边界符
                        memStream.Write(endBoundary, 0, endBoundary.Length);
                }
                webRequest.ContentLength = memStream.Length;
                var requestStream = webRequest.GetRequestStream();
                memStream.Position = 0;
                var tempBuffer = new byte[memStream.Length];
                memStream.Read(tempBuffer, 0, tempBuffer.Length);
                memStream.Close();
                requestStream.Write(tempBuffer, 0, tempBuffer.Length);
                requestStream.Close();
                using (HttpWebResponse res = (HttpWebResponse)webRequest.GetResponse())
                {
                    using (Stream resStream = res.GetResponseStream())
                    {
                        byte[] buffer = new byte[1024];
                        int read;
                        while ((read = resStream.Read(buffer, 0, buffer.Length)) > 0)
                        {
                            responseContent += Encoding.UTF8.GetString(buffer, 0, read);
                        }
                    }
                    res.Close();
                }
                return responseContent;
            }
            catch (Exception e)
            {
            }
            return null;
        }

        public class PostDateClass
        {
            /// <summary>
            /// 参数名称
            /// </summary>
            public string Key { get; set; }

            /// <summary>
            /// 参数值
            /// </summary>
            public string Value { get; set; }

            /// <summary>
            /// post数据类型
            /// </summary>
            public DateType PostDataType { get; set; } = DateType.StringType;

            public enum DateType
            {
                /// <summary>
                /// 字符串类型
                /// </summary>
                StringType = 0,

                /// <summary>
                /// 文件类型
                /// </summary>
                FileType = 1,

            }
        }


        /// <summary>
        /// 添加Host或Connection 的value值 (header里有些不太好添加的值，用此方法)
        /// </summary>
        /// <param name="header"></param>
        /// <param name="name"></param>
        /// <param name="value"></param>
        public static void SetHeaderValue(WebHeaderCollection header, string name, string value)
        {
            var property = typeof(WebHeaderCollection).GetProperty("InnerCollection",
                System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
            if (property != null)
            {
                var collection = property.GetValue(header, null) as NameValueCollection;
                collection[name] = value;
            }
        }

        #region 爬虫请求写法示例
        /// <summary>
        /// 获取百度site:域名 爬虫示例，包含header cookie gzip解压缩
        /// </summary>
        /// <param name="url">例如 https://www.baidu.com/s?wd=site%3Awww.123456.com </param>
        /// <returns></returns>
        private string GetBaiduPage(string url)
        {
            HttpWebRequest request = null;
            HttpWebResponse response = null;
            try
            {
                request = System.Net.WebRequest.Create(url) as HttpWebRequest;
                request.Method = "GET";
                request.Host = "www.baidu.com";
                
                request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36";
                request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3";

                //request.Connection = "keep-alive";
                //正常来说添加Connection值会报错，而且非必填项。但如果一定要给Connection添加值，用下面的方法。
                //SetHeaderValue(request.Headers, "Connection", "keep-alive");

                //如果有gzip压缩，自动解压缩
                request.AutomaticDecompression = DecompressionMethods.GZip;//自动解压缩 （gzip, deflate）

                //增加其他header属性
                request.Headers.Add("cache-control", "max-age=0");
                request.Headers.Add("Upgrade-Insecure-Requests", "1");
                request.Headers.Add("Sec-Fetch-User", "?1");
                request.Headers.Add("Sec-Fetch-Site", "none");
                request.Headers.Add("Sec-Fetch-Mode", "navigate");
                request.Headers.Add("Accept-Encoding", "gzip, deflate, br");
                request.Headers.Add("Accept-Language", "zh-CN,zh;q=0.9");

                //增加cookie值
                CookieCollection cookies = new CookieCollection();
                cookies.Add(new Cookie("BIDUPSID", "D80550B5F377F705B0387391E916CD9C"));
                cookies.Add(new Cookie("PSTM", "1571015334"));
                cookies.Add(new Cookie("BD_UPN", "12314753"));
                cookies.Add(new Cookie("BAIDUID", "7E289D5244475837F98CC5E2D641E014:FG"));
                cookies.Add(new Cookie("BDORZ", "B490B5EBF6F3CD402E515D22BCDA1598"));
                cookies.Add(new Cookie("MCITY", "-58%3A"));
                cookies.Add(new Cookie("BDUSS", "3c1S0xtQWd1bElVSGlxdS1sVTk0d1NucGRsd0wwT1Y2ZzV5WGlLc3dDNmZzZzVlRVFBQUFBJCQAAAAAAAAAAAEAAAClfvUDenkzMjAwMgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJ8l512fJeddQ"));
                cookies.Add(new Cookie("delPer", "0"));
                cookies.Add(new Cookie("BD_CK_SAM", "1"));
                cookies.Add(new Cookie("PSINO", "2"));
                cookies.Add(new Cookie("BD_HOME", "1"));
                cookies.Add(new Cookie("BDRCVFR[feWj1Vr5u3D]", "I67x6TjHwwYf0"));
                cookies.Add(new Cookie("H_PS_PSSID", "1423_21111_30210_20697_22158"));
                cookies.Add(new Cookie("COOKIE_SESSION", "5087_0_9_9_2_19_0_4_9_7_1_0_0_0_0_0_1575611490_0_1575617174%7C9%2317077_124_1575524447%7C9"));
                cookies.Add(new Cookie("sug", "3"));
                cookies.Add(new Cookie("sugstore", "1"));
                cookies.Add(new Cookie("ORIGIN", "2"));
                cookies.Add(new Cookie("bdime", "0"));
                cookies.Add(new Cookie("H_PS_645EC", "152cjmp168G1Y96YFvAzbyqeUnjPlhXlOYhjAxwMcI%2FrWppEwXzkPfYu%2Fto"));

                CookieContainer co = new CookieContainer();
                co.Add(new Uri(url), cookies);
                request.CookieContainer = co;

                response = request.GetResponse() as HttpWebResponse;
            }
            catch (WebException exception)
            {
                if (exception.Status == WebExceptionStatus.ProtocolError)
                {
                    response = (HttpWebResponse)exception.Response;
                }
                if (exception.Status == WebExceptionStatus.ConnectFailure)
                {
                    return exception.Message;
                }
            }
            catch (Exception ex)
            {
                if (response != null)
                {
                    response.Close();
                }
                return string.Empty;
            }

            if (response != null)
            {
                Encoding enc = string.IsNullOrEmpty(response.CharacterSet) ? Encoding.UTF8 : Encoding.GetEncoding(response.CharacterSet);
                //string html = Gzip.ReadGzip(response.GetResponseStream(), enc); //gzip 解压缩 或设置 request.AutomaticDecompression
                string html = string.Empty;
                using (StreamReader sr = new StreamReader(response.GetResponseStream(), enc))
                {html = sr.ReadToEnd();}

                response.Close();
                return html;
            }

            return string.Empty;
        }

        #endregion

        #region URL参数加密解密

        /// <summary>
        /// Base64 转 string
        /// </summary>
        /// <param name="base64"></param>
        /// <returns></returns>
        private static string Base64ToString(string base64)
        {
            try
            {
                char[] charBuffer = base64.ToCharArray();
                byte[] bytes = Convert.FromBase64CharArray(charBuffer, 0, charBuffer.Length);
                return Encoding.UTF8.GetString(bytes);
            }
            catch
            {
                return string.Empty;
            }
        }
        /// <summary>
        /// string 转 base64
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        private static string StringToBase64(string value)
        {
            try
            {
                byte[] bytValue = System.Text.Encoding.UTF8.GetBytes(value);

                return Convert.ToBase64String(bytValue);
            }
            catch
            {
                return string.Empty;
            }
        }



        /// <summary>
        /// 加密
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static string Url64Encode(string value)
        {
            if (string.IsNullOrEmpty(value)) return string.Empty;
            string s = StringToBase64(StringToBase64(value));

            return s.TrimEnd(new char[] { '=' });

        }

        public static string Url64Encode(int value)
        {
            return Url64Encode(value.ToString());
        }

        /// <summary>
        /// 解密
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static string Url64Decode(string value)
        {
            if (string.IsNullOrEmpty(value)) return string.Empty;

            string s = string.Empty;

            int nC = value.Length % 4;
            if (nC == 0)
            {
                s = value;
            }
            else
            {
                s = value + Repeat("=", 4 - nC);
            }
            return Base64ToString(Base64ToString(s));
        }
        /// <summary>
        /// 将字符串重复number次
        /// </summary>
        /// <param name="source"></param>
        /// <param name="number"></param>
        /// <returns></returns>
        private static string Repeat(string source, int number)
        {
            StringBuilder sb = new StringBuilder();
            int i = 0;
            for (i = 0; i < number; i++) sb.Append(source);
            return sb.ToString();
        }
        #endregion

        /// <summary>
        /// 取得客户真实IP(如果有代理，会返回多个ip地址)
        /// </summary>
        /// <returns></returns>
        public static string GetTrueUserIP()
        {
            string UserIP = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
            if (string.IsNullOrEmpty(UserIP))
                UserIP = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
            if (string.IsNullOrEmpty(UserIP))
                UserIP = HttpContext.Current.Request.UserHostAddress;
            if (UserIP == "::1")
                UserIP = "127.0.0.1";
            if (UserIP.IndexOf(".") == -1)//没有“.”肯定是非IPv4格式
                UserIP = "0.0.0.1";
            else
            {
                string temp = UserIP;
                UserIP = string.Empty;

                IPAddress ip;
                if (temp.IndexOf(",") != -1)
                {
                    //有“,”，估计多个代理。
                    temp = temp.Replace(" ", "").Replace("'", "");
                    string[] TempIPs = temp.Split(',');

                    StringBuilder sb = new StringBuilder();
                    foreach (var item in TempIPs)
                    {
                        if (IPAddress.TryParse(item, out ip))
                        {
                            sb.AppendFormat(",{0}", ip.ToString());
                            //UserIP += "," + ip.ToString();
                        }
                    }
                    if (sb.ToString().Length > 0)
                        UserIP = sb.ToString().Substring(1);
                }
                else
                {
                    if (IPAddress.TryParse(temp, out ip))
                        UserIP = ip.ToString();
                }

                if (UserIP.Length == 0)
                    UserIP = "0.0.0.2";
            }
            return UserIP;
            //https://www.cnblogs.com/a14907/p/6445431.html
            /*
             小结：
1、REMOTE_ADDR 不可被修改，但是可能会获得代理服务器的IP，而不是实际客户端的IP。
2、通过 HTTP_VIA、HTTP_X_FORWARDED_FOR 我们可以获得代理服务器所代理的信息，但是这依靠代理服务器的支持。另外，这两个值可以被修改。我们通过它获得的信息可能是不真实的。
另，HTTP_X_FORWARDED_FOR 的信息可能是一个集合，不含 REMOTE_ADDR 中的代理服务器IP。没有一个完美的解决获得客户端IP地址的方法，我们只能在上面2个信息中取舍。
             */
        }


        /// <summary>
        /// 获取用户操作系统信息
        /// </summary>
        /// <returns></returns>
        public static string GetUserOS()
        {
            string strAgentInfo = HttpContext.Current.Request.UserAgent;

            if (strAgentInfo.ContainsByIgnoreCase("NT 10") || strAgentInfo.ContainsByIgnoreCase("NT 6.4"))
            {
                return "Windows 10";
            }
            else if (strAgentInfo.ContainsByIgnoreCase("NT 6.3"))
            {
                return "Windows 8.1";
            }
            else if (strAgentInfo.ContainsByIgnoreCase("NT 6.2"))
            {
                return "Windows 8";
            }
            else if(strAgentInfo.ContainsByIgnoreCase("NT 6.1"))
            {
                return "Windows 7";
            }
            else if (strAgentInfo.ContainsByIgnoreCase("NT 6.0"))
            {
                return "Windows Vista/Server 2008";
            }
            else if (strAgentInfo.ContainsByIgnoreCase("NT 5.2"))
            {
                return "Windows 2003";
            }
            else if (strAgentInfo.ContainsByIgnoreCase("NT 5.1"))
            {
                return "Windows XP";
            }
            else if (strAgentInfo.ContainsByIgnoreCase("NT 5"))
            {
                return "Windows 2000";
            }
            else if (strAgentInfo.ContainsByIgnoreCase("NT 4.9"))
            {
                return "Windows ME";
            }
            else if (strAgentInfo.ContainsByIgnoreCase("NT 4"))
            {
                return "Windows NT4";
            }
            else if (strAgentInfo.ContainsByIgnoreCase("NT 98"))
            {
                return "Windows 98";
            }
            else if (strAgentInfo.ContainsByIgnoreCase("NT 95"))
            {
                return "Windows 95";
            }
            else if (strAgentInfo.ContainsByIgnoreCase("Mac"))
            {
                return "Mac";
            }
            else if (strAgentInfo.ContainsByIgnoreCase("unix"))
            {
                return "UNIX";
            }
            else if (strAgentInfo.ContainsByIgnoreCase("linux"))
            {
                return "Linux";
            }
            else if (strAgentInfo.ContainsByIgnoreCase("SunOS"))
            {
                return "SunOS";
            }

            return "其他系统";
        }

        /// <summary>
        /// 判断是否为手机端
        /// </summary>
        /// <returns></returns>
        public static bool IsMoblie()
        {
            string agent = (HttpContext.Current.Request.UserAgent + "").Trim().ToLower();

            if (agent == "" ||
                agent.IndexOf("mobile")       != -1 ||
                agent.IndexOf("mobi")         != -1 ||
                agent.IndexOf("nokia")        != -1 ||
                agent.IndexOf("samsung")      != -1 ||
                agent.IndexOf("sonyericsson") != -1 ||
                agent.IndexOf("mot")          != -1 ||
                agent.IndexOf("blackberry")   != -1 ||
                agent.IndexOf("lg")           != -1 ||
                agent.IndexOf("htc")          != -1 ||
                agent.IndexOf("j2me")         != -1 ||
                agent.IndexOf("ucweb")        != -1 ||
                agent.IndexOf("opera mini")   != -1 ||
                agent.IndexOf("mobi")         != -1 ||
                agent.IndexOf("android")      != -1 ||
                agent.IndexOf("iphone")       != -1)
            {
                //终端可能是手机
                return true;
            }

            return false;
        }

        /// <summary>
        /// 判断是否是微信客户端
        /// </summary>
        /// <returns></returns>
        public static bool IsWechat()
        {
            string param = HttpContext.Current.Request.ServerVariables["HTTP_USER_AGENT"];
            if (!string.IsNullOrEmpty(param) )
            {
                return param.ToLower().Contains("MicroMessenger".ToLower());
            }
            return false;
        }

        
        /// <summary>
        /// 动态添加页面中title,keywords,desription
        /// </summary>
        /// <param name="p">加载的页面</param>
        /// <param name="title">主标题</param>
        /// <param name="key">关键词</param>
        /// <param name="des">描述</param>
        public static void AddHeadSEO(Page p, string title, string key, string des)
        {
            HtmlMeta keywords = new HtmlMeta();
            HtmlMeta desription = new HtmlMeta();
            keywords.Name = "keywords";
            keywords.Content = key;
            desription.Name = "description";
            desription.Content = des;
            p.Header.Controls.Add(keywords);
            p.Header.Controls.Add(desription);
            p.Title = title ;
        }

        #region Gzip 压缩解压缩
        public class Gzip
        {
            /// <summary>
            /// 将Gzip的byte数组读取为字符串
            /// </summary>
            /// <param name="bytes"></param>
            /// <param name="ecd">编码规则</param>
            /// <returns></returns>
            public static string ReadGzip(byte[] bytes, Encoding ecd)
            {
                using (MemoryStream ms = new MemoryStream(bytes))
                {
                    return ReadGzip(ms, ecd);
                }
            }

            /// <summary>
            /// 将Gzip的byte数组读取为字符串
            /// </summary>
            /// <param name="ms">流</param>
            /// <param name="ecd">编码</param>
            /// <returns></returns>
            public static string ReadGzip(Stream ms, Encoding ecd)
            {
                using (GZipStream decompressedStream = new GZipStream(ms, CompressionMode.Decompress))
                {
                    using (StreamReader sr = new StreamReader(decompressedStream, ecd))
                    {
                        return sr.ReadToEnd();
                    }
                }
            }

            /// <summary>
            /// 将字符串压缩成Gzip格式的byte数组
            /// </summary>
            /// <param name="str"></param>
            /// <returns></returns>
            public static byte[] WriteGzip(string str)
            {
                byte[] rawData = System.Text.Encoding.UTF8.GetBytes(str);
                using (MemoryStream ms = new MemoryStream())
                {
                    GZipStream compressedzipStream = new GZipStream(ms, CompressionMode.Compress, true);
                    compressedzipStream.Write(rawData, 0, rawData.Length);
                    compressedzipStream.Close();
                    return ms.ToArray();
                }
            }
        }
        #endregion


        /// <summary>
        /// 获取url参数值
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        public static Dictionary<string, string> GetUrlQueryString(string url)
        {
            // https://www.cnblogs.com/cplemom/p/13585051.html

            if (string.IsNullOrWhiteSpace(url))
            {
                throw new ArgumentNullException("url");
            }
            var uri = new Uri(url);
            if (string.IsNullOrWhiteSpace(uri.Query))
            {
                return new Dictionary<string, string>();
            }
            //1.去除第一个前导?字符
            var dic = uri.Query.Substring(1)
                //2.通过&划分各个参数
                .Split(new char[] { '&' }, StringSplitOptions.RemoveEmptyEntries)
                //3.通过=划分参数key和value,且保证只分割第一个=字符
                .Select(param => param.Split(new char[] { '=' }, 2, StringSplitOptions.RemoveEmptyEntries))
                //4.通过相同的参数key进行分组
                .GroupBy(part => part[0], part => part.Length > 1 ? part[1] : string.Empty)
                //5.将相同key的value以,拼接
                .ToDictionary(group => group.Key, group => string.Join(",", group));

            return dic;
        }

        #region HttpContext 常用方法相关(记不住封装个)

        /// <summary>
        /// Server.MapPath 封装
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        public static string MapPath(string url)
        {
            return HttpContext.Current.Server.MapPath(url);
        }

        /// <summary>
        /// 获取带http的域名 http(s)://www.abc.com
        /// </summary>
        /// <param name="havePort">是否强制显示端口号(默认80或443端口不显示)</param>
        /// <returns></returns>
        public static string GetHttpHost(bool havePort = false)
        {
            string httpStr = "http://";
            if (HttpContext.Current.Request.Url.ToString().IndexOf("https://", StringComparison.OrdinalIgnoreCase) == 0)
            {
                httpStr = "https://";
            }
            string portStr = string.Empty;
            if (havePort)
            {
                portStr = ":" + HttpContext.Current.Request.Url.Port;
            }
            else
            {
                var defaultPorts = new int[] { 80, 443 };
                if (!defaultPorts.Contains(HttpContext.Current.Request.Url.Port))
                {
                    portStr = ":" + HttpContext.Current.Request.Url.Port;
                }
            }

            return httpStr + HttpContext.Current.Request.Url.Host + portStr;
        }

        #endregion
    }
}
